package com.boot.mall.search.thread;

import java.util.concurrent.*;

public class ThreadTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程启动中...");
        // 1.继承Thread，重写run方法
        //      Thread01 thread01 = new Thread01();
        //      thread01.start();
        // 2.实现Runnable接口
        //      Thread02 thread02 = new Thread02();
        //      new Thread(thread02).start();
        // 3.实现Callable接口
        FutureTask<Integer> task = new FutureTask<>(new Thread03());
        //      new Thread(task).start();
        //      System.out.println(task.get());
        // 4.线程池
/**
 * 构建线程池
 *  七大参数：
 *      corePoolSize：【核心线程数】 这些线程会一直存在线程池中，线程池一旦创建就会创建核心线程数，
 *          指定allowCoreThreadTimeOut核心线程才会过期
 *      maximumPoolSize：【最大线程总数】，用于控制资源使用
 *      keepAliveTime：【非核心线程生命周期】 除了核心线程之外的线程生命周期
 *      unit：【生命周期单位】 非核心线程生命周期的单位
 *      workQueue：【阻塞队列】 当所有线程都在执行，没有空闲线程时，多余的任务会被放在阻塞队列里面，
 *          一旦有线程空闲，就会从阻塞队列中取出任务执行
 *      threadFactory：【线程工厂】 创建线程时可以设置线程属性
 *      RejectedExecutionHandler handler：【阻塞队列拒绝策略】 当队列满了，按照指定的策略拒绝多余的任务
 *  工作顺序：
 *      1. 创建线程池，准备核心线程数量，准备执行任务
 *          1.1 当核心线程全被占用，新的任务会被放到阻塞队列当中，核心线程空闲就会到阻塞队列中取出任务执行
 *          1.2 当阻塞队列满了，直接新开线程执行任务，但是线程数最多开到Max指定的数量
 *          1.3 所有任务都执行完了，非核心线程就会在生命周期之后自动销毁，最终保持在核心线程数量
 *          1.4 如果线程数量已经达到Max，还有新的任务，就会指定的拒绝策略执行
 *          1.5 LinkedBlockingDeque<>()指定队列大小，默认是Integer类型的最大数，即2147483647
 *  面试题：
 *      一个线程池  core 5,max 20,queue 50,100个并发怎么处理
 *      首先核心线程core处理5个，队列进入50个，再开15个线程，从队列中取出15个任务处理，队列再进15个
 *      【线程懒加载，能不创建就不创建】
 *
 *
 */
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                5,
                20,
                10,
                TimeUnit.SECONDS,   //时间单位秒
                new LinkedBlockingDeque<>(10000),   //队列大小10000
                Executors.defaultThreadFactory(),   //默认的线程工厂
                new ThreadPoolExecutor.AbortPolicy()    //丢弃最新任务策略
        );

        Executors.newCachedThreadPool();

        System.out.println("主线程已结束...");
    }

    //继承Thread类
    public static class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("线程 "+Thread.currentThread().getName() + " 开始启动..");
            for (int i = 0; i < 3; i++) {
                System.out.println("线程 "+Thread.currentThread().getName() + "运行中.." + i);
            }
            System.out.println("线程 "+Thread.currentThread().getName() + " 启动结束..");
        }
    }

    public static class Thread02 implements Runnable{
        @Override
        public void run() {
            System.out.println("线程 "+Thread.currentThread().getName() + " 开始启动..");
            for (int i = 0; i < 3; i++) {
                System.out.println("线程 "+Thread.currentThread().getName() + "运行中.." + i);
            }
            System.out.println("线程 "+Thread.currentThread().getName() + " 启动结束..");
        }
    }

    public static class Thread03 implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            System.out.println("线程 "+Thread.currentThread().getName() + " 开始启动..");
            int i = 10 / 2;
            Thread.sleep(5000);
            System.out.println("线程 "+Thread.currentThread().getName() + " 启动结束..");
            return i;
        }
    }

}

